package icu.qx.wm.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import icu.qx.common.utils.CodeUtils;
import icu.qx.wm.domain.WmReturnMaterialList;
import icu.qx.wm.domain.WmStorageInfo;
import icu.qx.wm.dto.MaterialReturnDTO;
import icu.qx.wm.exception.MaterialReturnException;
import icu.qx.wm.mapper.WmReturnMaterialListMapper;
import icu.qx.wm.mapper.WmStorageInfoMapper;
import icu.qx.wm.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import icu.qx.wm.mapper.WmProductionMaterialReturnMapper;
import icu.qx.wm.domain.WmProductionMaterialReturn;
import icu.qx.wm.service.IWmProductionMaterialReturnService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 生产退料Service业务层处理
 *
 * @author alize
 * &#064;date  2024-06-26
 */
@Service
public class WmProductionMaterialReturnServiceImpl implements IWmProductionMaterialReturnService {
    private final WmProductionMaterialReturnMapper wmProductionMaterialReturnMapper;
    private final WmReturnMaterialListMapper wmReturnMaterialListMapper;
    private final WmStorageInfoMapper wmStorageInfoMapper;
    private final CodeUtils codeUtils;

    @Autowired
    public WmProductionMaterialReturnServiceImpl(
            WmProductionMaterialReturnMapper productionMaterialReturnMapper,
            WmReturnMaterialListMapper wmReturnMaterialListMapper,
            WmStorageInfoMapper wmStorageInfoMapper,
            CodeUtils codeUtils
    ) {
        this.wmProductionMaterialReturnMapper = productionMaterialReturnMapper;
        this.wmReturnMaterialListMapper = wmReturnMaterialListMapper;
        this.wmStorageInfoMapper = wmStorageInfoMapper;
        this.codeUtils = codeUtils;
    }

    /**
     * 查询生产退料
     *
     * @param pmrCode 生产退料主键
     * @return 生产退料
     */
    @Override
    public WmProductionMaterialReturn selectWmProductionMaterialReturnByPmrCode(String pmrCode) {
        WmProductionMaterialReturn wmProductionMaterialReturn = wmProductionMaterialReturnMapper.selectWmProductionMaterialReturnByPmrCode(pmrCode);
        List<WmReturnMaterialList> list = wmReturnMaterialListMapper.selectWmReturnMaterialListByPmrCode(pmrCode);
        if (!list.isEmpty()) {
            wmProductionMaterialReturn.setReturnMaterialList(list);
        }
        return wmProductionMaterialReturn;
    }

    /**
     * 查询生产退料列表
     *
     * @param wmProductionMaterialReturn 生产退料
     * @return 生产退料
     */
    @Override
    public List<WmProductionMaterialReturn> selectWmProductionMaterialReturnList(WmProductionMaterialReturn wmProductionMaterialReturn) {
        return wmProductionMaterialReturnMapper.selectWmProductionMaterialReturnList(wmProductionMaterialReturn);
    }

    /**
     * 新增生产退料
     *
     * @param wmProductionMaterialReturn 生产退料
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = MaterialReturnException.class)
    public int insertWmProductionMaterialReturn(WmProductionMaterialReturn wmProductionMaterialReturn) {
        try {
            wmProductionMaterialReturn.setCreateTime(DateUtils.getNowDate());
            wmProductionMaterialReturn.setCreateBy(SecurityUtils.getUsername());
            String pmrCode = codeUtils.generateCode("wm_production_material_return");
            wmProductionMaterialReturn.setPmrCode(pmrCode);

            int count = wmProductionMaterialReturnMapper.insertWmProductionMaterialReturn(wmProductionMaterialReturn);
            if (count <= 0) {
                throw new MaterialReturnException("插入产品退料失败");
            }

            List<WmReturnMaterialList> materialLists = wmProductionMaterialReturn.getReturnMaterialList();
            if (!materialLists.isEmpty()) {
                materialLists.forEach(item -> item.setPmrCode(pmrCode));

                int materialCount = 0;
                for (WmReturnMaterialList item : materialLists) {
                    item.setRmlMaterialCode(item.getGbsGood().getPdCode());
                    item.setRmlSlCode(item.getGbsGood().getStorageSlCode());
                    int i = wmReturnMaterialListMapper.insertWmReturnMaterialList(item);
                    if (i > 0) {
                        materialCount++;
                    } else {
                        throw new MaterialReturnException("插入物料清单失败");
                    }
                }
                return materialCount;
            }
            return count;
        } catch (Exception e) {
            // 捕获所有异常，并抛出自定义异常
            throw new MaterialReturnException("生产退料操作失败: " + e.getMessage(), e);
        }
    }

    /**
     * 修改生产退料
     *
     * @param wmProductionMaterialReturn 生产退料
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = MaterialReturnException.class)
    public int updateWmProductionMaterialReturn(WmProductionMaterialReturn wmProductionMaterialReturn) {
        try {
            // 更新生产退料单
            wmProductionMaterialReturn.setUpdateBy(SecurityUtils.getUsername());
            wmProductionMaterialReturn.setUpdateTime(DateUtils.getNowDate());
            int updateCount = wmProductionMaterialReturnMapper.updateWmProductionMaterialReturn(wmProductionMaterialReturn);
            if (updateCount == 0) {
                throw new MaterialReturnException("更新生产退料单失败");
            }

            // 获取当前数据库中的物料清单
            List<WmReturnMaterialList> existingMaterialLists = wmReturnMaterialListMapper.selectWmReturnMaterialListByPmrCode(wmProductionMaterialReturn.getPmrCode());

            // 比较并更新物料清单
            updateMaterialLists(wmProductionMaterialReturn.getPmrCode(), existingMaterialLists, wmProductionMaterialReturn.getReturnMaterialList());

            return updateCount;
        } catch (Exception e) {
            throw new MaterialReturnException("更新生产退料单时发生错误: " + e.getMessage(), e);
        }
    }

    private void updateMaterialLists(String pmrCode, List<WmReturnMaterialList> existingLists, List<WmReturnMaterialList> newLists) throws MaterialReturnException {
        Map<String, WmReturnMaterialList> existingMap = existingLists.stream()
                .collect(Collectors.toMap(WmReturnMaterialList::getRmlMaterialCode, Function.identity()));

        for (WmReturnMaterialList newItem : newLists) {
            WmReturnMaterialList existingItem = existingMap.remove(newItem.getRmlMaterialCode());
            if (existingItem == null) {
                // 新增项
                newItem.setPmrCode(pmrCode);
                int insertCount = wmReturnMaterialListMapper.insertWmReturnMaterialList(newItem);
                if (insertCount == 0) {
                    throw new MaterialReturnException("插入物料清单项失败");
                }
            } else {
                // 更新项
                if (!existingItem.equals(newItem)) {
                    newItem.setPmrCode(pmrCode);
                    int updateCount = wmReturnMaterialListMapper.updateWmReturnMaterialList(newItem);
                    if (updateCount == 0) {
                        throw new MaterialReturnException("更新物料清单项失败");
                    }
                }
            }
        }

        // 删除不再存在的项
        for (WmReturnMaterialList itemToDelete : existingMap.values()) {
            int deleteCount = wmReturnMaterialListMapper.deleteWmReturnMaterialListByPmrCode(pmrCode, itemToDelete.getRmlMaterialCode());
            if (deleteCount == 0) {
                throw new MaterialReturnException("删除物料清单项失败");
            }
        }
    }

    /**
     * 批量删除生产退料
     *
     * @param pmrCodes 需要删除的生产退料主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = MaterialReturnException.class)
    public int deleteWmProductionMaterialReturnByPmrCodes(String[] pmrCodes) {
        try {
            int num = wmReturnMaterialListMapper.selectMaterialListTotalByPmrCodes(pmrCodes);
            if (num > 0) {
                int count = wmReturnMaterialListMapper.deleteWmReturnMaterialListByPmrCodes(pmrCodes);
                if (count == 0) {
                    throw new MaterialReturnException("删除物料清单失败");
                }
            }
            return wmProductionMaterialReturnMapper.deleteWmProductionMaterialReturnByPmrCodes(pmrCodes);
        } catch (Exception e) {
            throw new MaterialReturnException("删除生产退料单失败: " + e.getMessage(), e);
        }
    }

    // 查询工艺路线
    @Override
    public List<Map<String, String>> selectRouteCode() {
        return wmProductionMaterialReturnMapper.selectRouteCode();
    }

    // 查询工序
    @Override
    public List<Map<String, String>> selectProcedureCode() {
        return wmProductionMaterialReturnMapper.selectProcedureCode();
    }

    /**
     * 查询生产退料物料清单列表
     *
     * @param wmReturnMaterialList 生产退料物料清单
     * @return 生产退料物料清单集合
     */
    @Override
    public List<WmReturnMaterialList> selectWmReturnMaterialList(WmReturnMaterialList wmReturnMaterialList) {
        return wmReturnMaterialListMapper.selectWmReturnMaterialList(wmReturnMaterialList);
    }

    // 查询班组列表
    @Override
    public List<PbsWorkGroupVo> selectPbsWorkGroupList() {
        return wmProductionMaterialReturnMapper.selectPbsWorkGroupList();
    }

    // 查询生产工单
    @Override
    public List<ProWorkOrderVo> selectWorkOrder(ProWorkOrderVo proWorkOrderVo) {
        return wmProductionMaterialReturnMapper.selectWorkOrder(proWorkOrderVo);
    }

    // 查询工单任务
    @Override
    public List<ProWorkTaskVo> selectProWorkTaskList(ProWorkTaskVo proWorkTaskVo) {
        return wmProductionMaterialReturnMapper.selectProWorkTaskList(proWorkTaskVo);
    }

    // 查询任务负责人
    @Override
    public String[] selectTaskManager() {
        return wmProductionMaterialReturnMapper.selectTaskManager();
    }

    // 查找物料
    @Override
    public List<MaterialListVo> selectMaterialList(MaterialListVo materialListVo) {
        return wmReturnMaterialListMapper.selectMaterialList(materialListVo);
    }

    // 查找单位
    @Override
    public List<UnitTypeVo> selectUnitList() {
        return wmReturnMaterialListMapper.selectUnitList();
    }

    // 退料单入库
    @Override
    @Transactional(rollbackFor = MaterialReturnException.class)
    public int storeMaterialReturn(MaterialReturnDTO materialReturnDTO) {
        try {
            if (materialReturnDTO.getMaterialList() == null || materialReturnDTO.getMaterialList().isEmpty()) {
                List<WmReturnMaterialList> list = wmReturnMaterialListMapper.selectWmReturnMaterialListByPmrCode(materialReturnDTO.getPmrCode());
                if (list.isEmpty()) {
                    throw new MaterialReturnException("物料清单为空");
                } else {
                    materialReturnDTO.setMaterialList(list);
                }
            }

            handleMaterialListEntry(materialReturnDTO.getMaterialList());

            WmProductionMaterialReturn wmProductionMaterialReturn = new WmProductionMaterialReturn();
            wmProductionMaterialReturn.setPmrCode(materialReturnDTO.getPmrCode());
            wmProductionMaterialReturn.setPmrStatus(materialReturnDTO.getPmrStatus());

            int result = wmProductionMaterialReturnMapper.updateWmProductionMaterialReturn(wmProductionMaterialReturn);
            if (result == 0) {
                throw new MaterialReturnException("更新生产退料失败");
            }
            return result;
        } catch (Exception e) {
            throw new MaterialReturnException("更新生产退料失败: " + e.getMessage(), e);
        }
    }

    private void handleMaterialListEntry(List<WmReturnMaterialList> materialList) {
        for (WmReturnMaterialList list : materialList) {
            String pdCode = list.getGbsGood().getPdCode();
            String prBatch = list.getPrdBatch();

            int count = wmStorageInfoMapper.selectWmStorageInfoCountByStPdCode(pdCode, prBatch);
            if (count > 0) {
                // 存在 比较库存
                BigDecimal oldStorage = wmStorageInfoMapper.selectWmStorageInfoStorage(pdCode, prBatch);
                BigDecimal returnNum = list.getRmlReturnNum();
                if (oldStorage.compareTo(returnNum) < 0) {
                    throw new MaterialReturnException("退料数量大于库存数量");
                } else if (oldStorage.compareTo(returnNum) == 0) {
                    wmStorageInfoMapper.deleteWmStorageInfo(pdCode, prBatch);
                } else {
                    BigDecimal newStorage = oldStorage.subtract(list.getRmlReturnNum());
                    updateInfoStorage(list, newStorage);
                }
            } else {
                // 不存在 直接抛出异常
                throw new MaterialReturnException("物料库存不存在");
            }
        }
    }

    private void updateInfoStorage(WmReturnMaterialList wmReturnMaterialList, BigDecimal newStorage) {
        WmStorageInfo info = setWmStorageInfo(wmReturnMaterialList);
        // 更新库存
        info.setStorageInfoNum(newStorage);
        // 设置更新信息
        info.setUpdateBy(SecurityUtils.getUsername());
        info.setUpdateTime(DateUtils.getNowDate());
        info.setCreateBy(null);
        info.setCreateTime(null);

        int i = wmStorageInfoMapper.updateWmStorageInfo(info);
        if (i == 0) {
            throw new MaterialReturnException("更新库存信息失败");
        }
    }

    // 设定库存信息
    private static WmStorageInfo setWmStorageInfo(WmReturnMaterialList returnMaterialList) {
        WmStorageInfo info = new WmStorageInfo();
        info.setStSlCode(returnMaterialList.getGbsGood().getStorageSlCode());
        info.setStPdCode(returnMaterialList.getGbsGood().getPdCode());
        info.setStorageInfoNum(returnMaterialList.getRmlReturnNum());
        info.setStorageInfoBatch(returnMaterialList.getPrdBatch());
        info.setSiProductionDate(returnMaterialList.getRmlProductionDate());
        info.setSiExpirationDate(returnMaterialList.getRmlExpirationDate());
        info.setCreateBy(SecurityUtils.getUsername());
        info.setCreateTime(DateUtils.getNowDate());
        return info;
    }
}
